package com.ysd.lis.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ysd.common.Result;
import com.ysd.lis.entity.ReadExcelData;
import com.ysd.lis.entity.WkEmployee;
import com.ysd.lis.entity.WkSchduleType;
import com.ysd.lis.entity.WkScheRecs;
import com.ysd.lis.listener.ReadExcelDataListener;
import com.ysd.lis.mapper.SchduleTypeMapper;
import com.ysd.lis.mapper.WkEmployeeMapper;
import com.ysd.lis.mapper.WkScheRecsMapper;
import com.ysd.lis.request.Resp;
import com.ysd.lis.request.ScheColumnDataParams;
import com.ysd.lis.request.UploadFileParams;
import com.ysd.lis.service.WkScheRecsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * <p>
 * 排班信息表 服务实现类
 * </p>
 *
 * @author LiuQi
 * @since 2024-02-28
 */
@Slf4j
@Service
public class WkScheRecsServiceImpl extends ServiceImpl<WkScheRecsMapper, WkScheRecs> implements WkScheRecsService {

    @Autowired
    WkScheRecsMapper wkScheRecsMapper;
    @Autowired
    WkEmployeeMapper wkEmployeeMapper;
    @Autowired
    SchduleTypeMapper schduleTypeMapper;

    public static final String[] days = new String[]{"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};

    @Override
    public Result getColumnData(String dateString) {
        Map<String, Object> resultMap = new HashMap<>();
        List<ScheColumnDataParams> columnList = new ArrayList<>();
        Date date = DateUtil.parse(dateString, "yyyy-MM-dd");
        // 获取指定月份总天数
        int currentMonthCount = DateUtil.lengthOfMonth(DateUtil.month(date) + 1, DateUtil.isLeapYear(DateUtil.year(date)));
        // 获取指定月份第一天
        DateTime dateTime = DateUtil.beginOfMonth(date);
        Date date1 = dateTime.toJdkDate();
        for (int i = 1; i <= currentMonthCount; i++) {
            ScheColumnDataParams scheColumnDataParams = new ScheColumnDataParams();
            scheColumnDataParams.setField("col" + i);
            scheColumnDataParams.setTitle(i + "");
            scheColumnDataParams.setYear(DateUtil.year(date1) + "");
            scheColumnDataParams.setMonth(DateUtil.month(date1) + 1 + "");
            scheColumnDataParams.setWeek(days[DateUtil.dayOfWeek(date1) - 1]);
            scheColumnDataParams.setDay(StrUtil.fillBefore(i + "", "0".charAt(0), 2));
            scheColumnDataParams.setDatestr(DateUtil.format(date1, "yyyy-MM-dd"));
            scheColumnDataParams.setCurDay(DateUtil.isSameDay(date1, new Date()));
            date1 = DateUtil.offsetDay(date1, 1);
            columnList.add(scheColumnDataParams);
        }
        LambdaQueryWrapper<WkScheRecs> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.between(WkScheRecs::getRecDate, DateUtil.beginOfMonth(date), DateUtil.endOfMonth(date));
        List<WkScheRecs> wkScheRecs = wkScheRecsMapper.selectList(lambdaQueryWrapper);
        List<Map<String, Object>> list = buildResultDataList(columnList, wkScheRecs);
        resultMap.put("dataList", list);
        resultMap.put("columnList", columnList);
        return Result.succ(1, "查询成功", resultMap);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result saveBatchSche(List<WkScheRecs> ScheRecs) {
        if (ScheRecs.size() > 0) {
            deleteBatch(ScheRecs.get(0).getEmployeeId(), DateUtil.format(ScheRecs.get(0).getRecDate(), "yyyy-MM-dd"));
            boolean b = this.saveBatch(ScheRecs);
            return Result.succ(1, "批量保存成功！", b);
        } else {
            return Result.fail("保存失败，参数列表为空！");
        }
    }

    @Override
    public Result deleteScheRecsByDate(String employeeId, String recDate) {
        int i = deleteBatch(employeeId, recDate);
        return Result.succ(1, "删除成功", i);
    }

    public int deleteBatch(String employeeId, String recDate) {
        LambdaQueryWrapper<WkScheRecs> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(WkScheRecs::getEmployeeId, employeeId)
                .between(WkScheRecs::getRecDate, DateUtil.beginOfDay(DateUtil.parse(recDate, "yyyy-MM-dd").toJdkDate()), DateUtil.endOfDay(DateUtil.parse(recDate, "yyyy-MM-dd").toJdkDate()));
        int delete = wkScheRecsMapper.delete(lambdaQueryWrapper);
        return delete;
    }

    @Override
    public Result deleteByEmployeeId(String employeeId, String recDate) {
        LambdaQueryWrapper<WkScheRecs> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(WkScheRecs::getEmployeeId, employeeId)
                .between(WkScheRecs::getRecDate, DateUtil.beginOfMonth(DateUtil.parse(recDate, "yyyy-MM-dd").toJdkDate()), DateUtil.endOfMonth(DateUtil.parse(recDate, "yyyy-MM-dd").toJdkDate()));
        int delete = wkScheRecsMapper.delete(lambdaQueryWrapper);
        return Result.succ(1, "删除成功", delete);
    }

    public List<Map<String, Object>> buildResultDataList(List<ScheColumnDataParams> columnList, List<WkScheRecs> ScheRecs) {
        List<Map<String, Object>> resultList = new ArrayList<>();
        // 根据员工id分组
        Map<String, List<WkScheRecs>> employeeIdMap = ScheRecs.stream().collect(Collectors.groupingBy(WkScheRecs::getEmployeeId));
        employeeIdMap.forEach((employeeId, value) -> {
            Map<Timestamp, List<WkScheRecs>> recDateMap = value.stream().collect(Collectors.groupingBy(WkScheRecs::getRecDate));
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("employeeId", employeeId);
            columnList.forEach(item -> {
                recDateMap.forEach((recDateKey, recDateValue) -> {
                    String format = DateUtil.format(DateUtil.date(recDateKey), "yyyy-MM-dd");
                    if (format.equals(item.getDatestr())) {
                        resultMap.put(item.getField(), recDateValue);
                    }
                });
            });
            resultList.add(resultMap);
        });
        return resultList;
    }

    /**
     * 下月快速排班 先清空数据， 再生成数据
     *
     * @param currentMonth
     * @return
     */
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result quicklyNextMonthScheRecs(String currentMonth) {
        clearCurMonthData(currentMonth, 1);
        LambdaQueryWrapper<WkScheRecs> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.between(WkScheRecs::getRecDate, DateUtil.beginOfMonth(DateUtil.parse(currentMonth, "yyyy-MM-dd").toJdkDate()), DateUtil.endOfMonth(DateUtil.parse(currentMonth, "yyyy-MM-dd").toJdkDate()));
        List<WkScheRecs> wkScheRecs = wkScheRecsMapper.selectList(lambdaQueryWrapper);
        if (CollUtil.isEmpty(wkScheRecs)) {
            throw new RuntimeException("当前月份未查询到数据！！ 排班失败！");
        }
        List<WkScheRecs> collect = wkScheRecs.stream().map(scheRecs -> {
            WkScheRecs wkScheRecs1 = new WkScheRecs();
            BeanUtil.copyProperties(scheRecs, wkScheRecs1);
            wkScheRecs1.setId(null);
            if (Integer.parseInt(wkScheRecs1.getMonth()) + 1 > 12) {
                wkScheRecs1.setYear(Integer.parseInt(wkScheRecs1.getYear()) + 1 + "");
                wkScheRecs1.setMonth("1");
            } else {
                wkScheRecs1.setMonth(Integer.parseInt(wkScheRecs1.getMonth()) + 1 + "");
            }
            wkScheRecs1.setRecDate(DateUtil.offsetMonth(wkScheRecs1.getRecDate(), 1).toTimestamp());
            wkScheRecs1.setWeek(days[DateUtil.dayOfWeek(wkScheRecs1.getRecDate()) - 1]);
            return wkScheRecs1;
        }).collect(Collectors.toList());
        boolean b = this.saveBatch(collect);
        return Result.succ(1, "下月快速排班完成！", b);
    }

    /**
     * 检验科排班
     *
     * @param recDate
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result lisDeptDataImport(String recDate) {
        clearCurMonthData(recDate, 0);
        LambdaQueryWrapper<WkEmployee> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(WkEmployee::getDelFlag, 0);
        List<WkEmployee> wkEmployees = wkEmployeeMapper.selectList(lambdaQueryWrapper);
        Date date = DateUtil.parse(recDate, "yyyy-MM-dd").toJdkDate();
        List<WkScheRecs> collect = wkEmployees.stream().map(employee -> {
            WkScheRecs wkScheRecs = new WkScheRecs();
            wkScheRecs.setEmployeeId(employee.getId());
            wkScheRecs.setRecDate(new Timestamp(date.getTime()));
            wkScheRecs.setYear(DateUtil.year(date) + "");
            wkScheRecs.setMonth(DateUtil.month(date) + "");
            return wkScheRecs;
        }).collect(Collectors.toList());
        this.saveBatch(collect);
        return Result.succ(1, "数据插入成功！", "");
    }

    public void clearCurMonthData(String recDate, int offSet) {
        DateTime startTime = DateUtil.beginOfMonth(DateUtil.offsetMonth(DateUtil.parse(recDate, "yyyy-MM-dd").toJdkDate(), offSet));
        DateTime endTime = DateUtil.endOfMonth(DateUtil.offsetMonth(DateUtil.parse(recDate, "yyyy-MM-dd").toJdkDate(), offSet));
        LambdaQueryWrapper<WkScheRecs> deleteWrapper = new LambdaQueryWrapper<>();
        deleteWrapper.between(WkScheRecs::getRecDate, startTime, endTime);
        wkScheRecsMapper.delete(deleteWrapper);
    }

    /**
     * 导入排班数据
     *
     * @param uploadFileParams
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @SneakyThrows
    @Override
    public Result importExcelData(UploadFileParams uploadFileParams) {
        // 读取excel 数据
        EasyExcel.read(uploadFileParams.getFile().getInputStream(), ReadExcelData.class, new ReadExcelDataListener()).sheet().headRowNumber(4).doRead();
        Resp resp = ReadExcelDataListener.RESP.get();
        List<ReadExcelData> importList = resp.getImportList();
        Map<Integer, String> headMap = resp.getHeadMap();
       if (CollUtil.isEmpty(importList) || CollUtil.isEmpty(headMap)) {
           throw new NullPointerException("表格数据为空！");
       }
        // 删除当前月份数据
        Date clearDate = DateUtil.parse(headMap.get(4), "yyyy/MM/dd").toJdkDate();
        String format = DateUtil.format(clearDate, "yyyy-MM-dd");
        clearCurMonthData(format, 0);
        // 查找类型数据
        LambdaQueryWrapper<WkSchduleType> typeLambdaQueryWrapper = new LambdaQueryWrapper<>();
        typeLambdaQueryWrapper.eq(WkSchduleType::getDelFlag, 0);
        Map<String, WkSchduleType> schduleTypeMap = schduleTypeMapper.selectList(typeLambdaQueryWrapper).stream().collect(Collectors.toMap(WkSchduleType::getSymbol, wkSchduleType -> wkSchduleType, (k1, k2) -> k1));
        List<WkScheRecs> resultSches = new ArrayList<>();
        for (int i = 0; i < importList.size(); i++) {
            ReadExcelData readExcelData = importList.get(i);
            Map<String, String> dataMap = BeanUtils.describe(readExcelData);
            final AtomicInteger index = new AtomicInteger(1);
            headMap.forEach((key, value) -> {
                String s = dataMap.get("col_" + index.getAndAdd(1));
                if (!"休".equals(s) && StrUtil.isNotEmpty(s) && schduleTypeMap.containsKey(s)) {
                    Date date = DateUtil.parse(value, "yyyy/MM/dd").toJdkDate();
                    WkScheRecs wkScheRecs = new WkScheRecs();
                    wkScheRecs.setEmployeeId(readExcelData.getId());
                    wkScheRecs.setYear(DateUtil.year(date) + "");
                    wkScheRecs.setMonth(DateUtil.month(date) + 1 + "");
                    wkScheRecs.setDay(StrUtil.fillBefore(key + "", "0".charAt(0), 2));
                    wkScheRecs.setWeek(days[DateUtil.dayOfWeek(date) - 1]);
                    wkScheRecs.setRecDate(new Timestamp(date.getTime()));
                    wkScheRecs.setScheTypeId(schduleTypeMap.get(s).getId());
                    wkScheRecs.setScheValue(schduleTypeMap.get(s).getSymbol());
                    wkScheRecs.setTexColor(schduleTypeMap.get(s).getWordColor());
                    wkScheRecs.setBgColor(schduleTypeMap.get(s).getBgColor());
                    resultSches.add(wkScheRecs);
                }
            });
        }
        log.info("数据集合 resultSches = {}", resultSches);
        this.saveBatch(resultSches);
        // 清除数据
        ReadExcelDataListener.RESP.remove();
        return Result.succ(1, "导入成功", "");
    }

}
